<?php
require_once $_SERVER['DOCUMENT_ROOT'].'/model/Service/Service.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/model/DAO/DAOManager.php';
require_once $_SERVER['DOCUMENT_ROOT'].'/exceptions/DataBaseException.php';
/**
 * Класс - оболочка для сервисов 
 * Выполняет работу с транзакциями
 */
class DecoratorService {
	/*
	 * Ссылка на текущий сервис
	*/
	private $service;

	/*
	 * Параметризованный конструктор
	* @param $service сервис
	*/
	public function DecoratorService($service) {
		//parent::__construct($service->daoManager);
		$this->service = $service;
	}

	/*
	 * Функция, котороя вызывается при обращении к несуществеющим методам
	* @param $name имя вызывыемого метода
	* @param $params массив аргументов этого метода
	*/

	public function __call($name, $params) {
		/*
		 * Начинаем выполнять "оболочку"
		*/
		$this->service->daoManager->transactionBegin();
		echo "::: НАЧИНАЕМ ТРАНЗАКЦИЮ ::{";
		try{
			/*
			 * Создаем объект класса ReflectionMethod который умеет у переданного объекта вызывать
			* нужное действие
			* @param get_class($this->service) имя сервиса
			* @param имя метода
			*/

			$method = new ReflectionMethod(get_class($this->service), $name);
			echo get_class($this->service)."->";
			echo $name;
			/*
			 * Выполняем нужное действие при помощи метода invokeArgs,
			* в качестве параметров передавая сервис и массив параметров этого метода
			*/
			$return = $method->invokeArgs($this->service, $params);
				
			$this->service->daoManager->transactionCommit();
			echo "}:: КОММИТИМ ТРАНЗАКЦИЮ :::";
				
			return $return;

		}catch(DataBaseException $exc){
			/* Может случитсья, что транзакиця не начнется, тогда откат транзакции сгенерирует ошибку
			 * Поэтому просто "душим" эту ошибку и ничего не делаем, так как если транзакция не началась,
			 * то и выполнять никаких действий с базой данных не нужно
			 */
			try{
				$this->service->daoManager->transactionRollback();
				echo "}:: ОТКАТЫВАЕМ ТРАНЗАКЦИЮ :::";
			}catch(DataBaseException $exc){
			}
			throw $exc; // Выбрасываем исключение, если не удалось выпонить действие 
		}
	}
}
?>